Retool で AssumeRole してDynamoDBテーブルにアクセスする(アクセスキーが流出しても、被害を最小限にしよう)
いろんなデータベースやAPIと接続してWebアプリをサクッと作れるRetoolですが、DynamoDBと連携する場合は、IAMユーザのアクセスキーを使います。 もし、アクセスキーが流出したら一大事です。 そこで、AssumeRoleを使って、少しでも影響が小さくなる方法を試してみました。
Retoolについては、下記をご覧ください。
おすすめの方
- RetoolでAssumeRoleしたい方
IAMユーザとIAMロールと実験用のDynamoDBテーブルを作成する
CloudFormationテンプレート
下記を作成します。
- Retool用のIAMユーザ
- Retool用のIAMユーザに付与するIAMポリシー(AssumeRoleのみ可能)
- Retool用のIAMユーザがAssumeRoleするIAMロール(DynamoDBに対する操作権限のみ)
- DynamoDBテーブル
AssumeRoleを活用すると、「Retool用のIAMユーザ」のアクセスキーが流出しても、AssumeRoleしかできません。 また、AssumeRoleする条件として「RetoolのIPアドレスのみ許可」しています。 そのため、第三者がアクセスキーを使っても、Retool以外はAssumeRoleできず、結果としてDynamoDBにアクセスできません。
AWSTemplateFormatVersion: 2010-09-09 Description: IAM and DynamoDB for Retool Resources: # Retool用のIAMユーザ RetoolUser: Type: AWS::IAM::User Properties: UserName: retool-user # Retool用のIAMユーザに付与するIAMポリシー(AssumeRoleのみ可能) # -> もし、アクセスキーが流出しても、AssumeRoleしかできない RetoolUserPoricy: Type: AWS::IAM::Policy Properties: PolicyName: retool-user-policy PolicyDocument: Version: "2012-10-17" Statement: - Effect: "Allow" Action: "sts:AssumeRole" Resource: !GetAtt RetoolRole.Arn Users: - !Ref RetoolUser # Retool用のIAMユーザがAssumeRoleするIAMロール(DynamoDBに対する操作権限のみ) RetoolRole: Type: AWS::IAM::Role Properties: RoleName: retool-user-role AssumeRolePolicyDocument: Version: "2012-10-17" Statement: - Effect: "Allow" Action: "sts:AssumeRole" Principal: AWS: - !GetAtt RetoolUser.Arn Condition: IpAddress: aws:SourceIp: # Retoolからのアクセスのみ、AssumeRoleできる # IP Addresss -> https://docs.retool.com/docs/connecting-your-database - 13.80.4.170/32 - 13.93.15.89/32 - 13.93.15.84/32 - 13.76.231.249/32 - 13.76.97.52/32 - 13.76.194.227/32 - 52.177.12.28/32 - 52.177.12.26/32 - 52.177.118.220/32 - 52.175.194.171/32 - 52.175.251.223/32 - 52.247.195.225/32 Policies: - PolicyName: retool-user-role-policy PolicyDocument: Version: "2012-10-17" Statement: - Effect: "Allow" Action: - "dynamodb:ListTables" Resource: "*" - Effect: "Allow" Action: - "dynamodb:DeleteItem" - "dynamodb:ListTagsOfResource" - "dynamodb:DescribeReservedCapacityOfferings" - "dynamodb:DescribeTable" - "dynamodb:GetItem" - "dynamodb:DescribeContinuousBackups" - "dynamodb:DescribeLimits" - "dynamodb:BatchGetItem" - "dynamodb:BatchWriteItem" - "dynamodb:PutItem" - "dynamodb:ListBackups" - "dynamodb:Scan" - "dynamodb:Query" - "dynamodb:DescribeStream" - "dynamodb:UpdateItem" - "dynamodb:DescribeTimeToLive" - "dynamodb:ListStreams" - "dynamodb:DescribeGlobalTableSettings" - "dynamodb:ListGlobalTables" - "dynamodb:GetShardIterator" - "dynamodb:DescribeGlobalTable" - "dynamodb:DescribeReservedCapacity" - "dynamodb:DescribeBackup" - "dynamodb:GetRecords" Resource: !GetAtt RetoolDeviceTable.Arn MaxSessionDuration: 3600 # DynamoDBテーブル RetoolDeviceTable: Type: AWS::DynamoDB::Table Properties: TableName: retool-device-table BillingMode: PAY_PER_REQUEST AttributeDefinitions: - AttributeName: deviceId AttributeType: S KeySchema: - AttributeName: deviceId KeyType: HASH Outputs: RetoolRoleArn: Value: !GetAtt RetoolRole.Arn
Retoolで操作するDynamoDBテーブルが決まっている場合、dynamodb:ListTables
以外は、Resource
にDynamoDBテーブルのARNを指定するとさらに安全になります。
デプロイ
aws cloudformation deploy \ --template-file aws.yaml \ --stack-name IAM-and-Retool-Sample-Stack \ --capabilities CAPABILITY_NAMED_IAM
アクセスキー取得
aws iam create-access-key \ --user-name retool-user
IAMロールのARNを取得
aws cloudformation describe-stacks \ --stack-name IAM-and-Retool-Sample-Stack \ --query 'Stacks[].Outputs'
手元のPCで、AssumeRoleできないことを確認する
AsssumeRoleの条件に「RetoolのIPアドレス」を指定しているので、手元のPCからAssumeRoleできないことを確認します。
アクセスキーを環境変数に登録する
さきほど取得したアクセスキーを環境変数に設定します。
export AWS_ACCESS_KEY_ID=xxx export AWS_SECRET_ACCESS_KEY=yyy export AWS_DEFAULT_REGION=ap-northeast-1
この状態だと、DynamoDBテーブルにアクセスできない
Retool用のIAMユーザには、AssumeRoleする権限のみを付与しているため、DynamoDBテーブルにアクセスできません。
$ aws dynamodb list-tables An error occurred (AccessDeniedException) when calling the ListTables operation: User: arn:aws:iam::000000000000:user/retool-user is not authorized to perform: dynamodb:ListTables on resource: arn:aws:dynamodb:ap-northeast-1:000000000000:table/*
AssumeRoleもできない
さきほど取得した「AssumeRole用のARN」を指定します。許可されていないIPアドレスなので、AssumeRoleできません。
$ aws sts assume-role \ --role-arn arn:aws:iam::000000000000:role/retool-user-role \ --role-session-name local-test \ --duration-seconds 900 An error occurred (AccessDenied) when calling the AssumeRole operation: User: arn:aws:iam::000000000000:user/retool-user is not authorized to perform: sts:AssumeRole on resource: arn:aws:iam::000000000000:role/retool-user-role
Retoolのリソースを作成する
必要事項を入力して、DynamoDBに対するリソースを作成します。
「Role to assume (ARN)」が未入力の場合、「Test Connection」が失敗します。
「Role to assume (ARN)」を入力すると、接続成功しました。
Retoolでデータ取得を確認する
適当なデータをDynamoDBテーブルに格納する
RetoolのアプリでDynamoDBテーブルのデータを確認する
以前に作成したアプリを流用します。
TableのResource
とTable
をさきほど作成したリソースとDynamoDBテーブルに変更します。
Method
はscan
を指定します。
「Save & Run」を選択すると、無事にデータ取得できました!
異なるDynamoDBテーブルには、アクセスできない
アクセスを許可していないDynamoDBテーブルの中身は、表示できません。期待通りですね。
さいごに
少し手間かもしれませんが、安全性が格段に向上します。 精神衛生上も気が楽になりますので、おすすめです。